

#ifndef XOTA_H__
#define XOTA_H__

#include <stdint.h>

#define XOTA_PB_VERSION		0x01030200

typedef enum{
	PB_INIT_SIGN = 1, 

	PB_INIT_HASH, 
	PB_INIT_CRC32, 
	PB_INIT_OTA_TYPE, 
	PB_INIT_APP_SIZE, 
	PB_INIT_SD_SIZE, 
	PB_INIT_BL_SIZE, 
	PB_INIT_FW_VER, 
	PB_INIT_HW_VER, 
	PB_INIT_SD_FWID, 	
	PB_INIT_APP_FWID, 
    PB_INIT_OPTION, 
}PB_INIT_TYPE; 

typedef enum{
    OTA_EPB_SUCCESS = 0, 
    
    OTA_EPB_ERR_INVALID_LENGTH,	// 1
	OTA_EPB_ERR_INVALID_FORMAT, // 2
    
	OTA_EPB_ERR_DATA_SIZE_ERROR , // 3
	OTA_EPB_ERR_RESOURCE_INSUFFICIENT, // 4  
	OTA_EPB_ERR_SUB_FUNCTION_NOT_SUPPORTED , // 5  
	OTA_EPB_ERR_NO_MEM,     // 6
	OTA_EPB_ERR_ADDR_RESP,  // 7 
	OTA_EPB_ERR_INVALID_KEY, //8 
	OTA_EPB_ERR_DELAY_NOT_EXPIRED_TIME, // 9   
	OTA_EPB_ERR_INVALID_STATE, // 10
	OTA_EPB_ERR_INVALID_PARAMS, // 11
	OTA_EPB_ERR_BUSY, // 12 
	OTA_EPB_ERR_INVALID_ADDR, // 13 
	OTA_EPB_ERR_NULL,  //14 
	OTA_EPB_ERR_INVALID_OBJECT, //15
	OTA_EPB_ERR_OPERATE_CODE_NOT_PERMITTED, //16
	OTA_EPB_ERR_VERSION_TOO_LOW, //17
	OTA_EPB_ERR_SIGNATURE_TYPE_NOT_SUPPORTED, //18
	OTA_EPB_ERR_SIGNATURE_VERIFY_FAIL, //19 
	OTA_EPB_ERR_HASH_NOT_FOUND, // 20
	OTA_EPB_ERR_APP_SIZE, // 21
	OTA_EPB_ERR_FIND_HASH_FAIL, // 22
	OTA_EPB_ERR_FIRMWARE_HASH, // 23
	OTA_EPB_ERR_FIMRWARE_CRC, //24 
	OTA_EPB_ERR_POWER_LOW,  //25 
	OTA_EPB_ERR_TIMEOUT, //26 
	OTA_EPB_ERR_HASH_TYPE_NOT_SUPPORTED, //27
	OTA_EPB_ERR_FIRMWARE_TYPE_NOT_SUPPORTED, //28 
    OTA_EPB_ERR_CTRL_FLAG_MISSED, // 29
	OTA_EPB_ERR_FIRMWARE_SIZE_TOO_LARGE, // 30 
    OTA_EPB_ERR_PROG_ERROR, //31 
	OTA_EPB_ERR_PROJ_CODE_INVALID, //32
    
	OTA_EPB_ERR_UNKNOWN= 0xff, 
}ota_pb_err_code_t; 


typedef enum
{
    OTA_FW_TYPE_APPLICATION = 0,
    OTA_FW_TYPE_SOFTDEVICE = 1,
    OTA_FW_TYPE_BOOTLOADER = 2,
    OTA_FW_TYPE_SOFTDEVICE_BOOTLOADER = 3,	
    OTA_FW_TYPE_TP_FIRMWARE = 4,
    OTA_FW_TYPE_FONT_LIBRARY = 5,
    OTA_FW_TYPE_IMAGE_LIBRARY = 6,
    OTA_FW_TYPE_CUSTOM_WATCHFACE = 7, 
    OTA_FW_TYPE_COUNT 
} ota_fw_type_t;
#define OTA_FW_TYPE_MIN OTA_FW_TYPE_APPLICATION
#define OTA_FW_TYPE_MAX OTA_FW_TYPE_SOFTDEVICE_BOOTLOADER
#define OTA_FW_TYPE_ARRAYSIZE (OTA_FW_TYPE_COUNT)

typedef enum
{
    OTA_HASH_TYPE_NO_HASH = 0,
    OTA_HASH_TYPE_SHA256 = 1,
    OTA_HASH_TYPE_MD5 = 2, 
	OTA_HASH_TYPE_LAST, 
} ota_hash_type_t;
#define OTA_HASH_TYPE_MIN OTA_HASH_TYPE_NO_HASH
#define OTA_HASH_TYPE_MAX OTA_HASH_TYPE_MD5
#define OTA_HASH_TYPE_ARRAYSIZE ((ota_hash_type_t)(OTA_HASH_TYPE_LAST))

typedef enum
{
    OTA_SIGNATURE_TYPE_ECDSA_P256_SHA256 = 0,
	OTA_SIGNATURE_TYPE_ED25519 = 1, 
	OTA_SIGNATURE_TYPE_MD5, 
	OTA_SIGNATURE_TYPE_LAST
} ota_signature_type_t;
#define OTA_SIGNATURE_TYPE_MIN OTA_SIGNATURE_TYPE_ECDSA_P256_SHA256
#define OTA_SIGNATURE_TYPE_MAX OTA_SIGNATURE_TYPE_MD5
#define OTA_SIGNATURE_TYPE_ARRAYSIZE ((ota_signature_type_t)(OTA_SIGNATURE_TYPE_MD5))

/* Struct definitions */
//typedef PB_BYTES_ARRAY_T(32) ota_hash_hash_t;
typedef struct{
	uint8_t 	size; 
	uint8_t 	bytes[32]; 
}ota_hash_hash_t; 

typedef struct {
    ota_hash_type_t hash_type;
    ota_hash_hash_t hash;
/* @@protoc_insertion_point(struct:ota_hash_t) */
} ota_hash_t;

typedef struct{
	uint8_t has_fw_version;
	uint32_t fw_version; 
	uint8_t has_hw_version; 
	uint32_t hw_version; 
	uint8_t sd_req_count; 
	uint32_t sd_req[4]; 
	uint8_t has_type; 
	ota_fw_type_t type;
	
	uint8_t has_sd_size; 
	uint32_t sd_size; 
	uint8_t has_bl_size; 
	uint32_t bl_size; 
	uint8_t has_app_size; 
	uint32_t app_size; 
	
	uint8_t has_hash; 
	ota_hash_t	hash; 	
	uint8_t has_crc; 
	uint32_t 	crc32; 
    
	uint8_t has_app_fwid;
	uint32_t app_fwid;

    uint8_t has_option;
    uint8_t len_of_option;
    uint8_t *option;

}ota_pb_init_command_t; 

typedef struct{
	uint8_t 	size; 
	uint8_t 	bytes[64]; 
}ota_signed_command_signature_t;

typedef struct{	
	ota_signature_type_t signature_type; 
	ota_signed_command_signature_t signature;
}pb_signed_command_t; 

typedef struct{
	uint8_t has_init; 
	ota_pb_init_command_t init; 
	
	uint8_t has_signed_command; 
	pb_signed_command_t sign_command; 
}ota_pb_create_command_t; 

typedef struct{
	uint32_t 	offset; 
	uint16_t 	size; 
	uint8_t* 	p_data; 	
}ota_pb_write_command_t; 

typedef struct
{
    uint8_t * p_value;
    uint32_t  length;

} ota_value_length_t;


#define OTA_PB_SIGNED_COMMAND_SIZE		(40)	//32hash + 4type 
#define OTA_PB_CREATE_COMMAND_SIZE		(152)	//
#define OTA_PB_WRITE_COMMAND_MIN_SIZE	(4 + 4 ) 
#define OTA_PB_WRITE_COMMAND_SIZE		(256 + 4)//offset + fw 


int xota_init_decode(    uint8_t * p_data,
                        uint16_t len,
                        ota_pb_create_command_t * p_init,
                        ota_value_length_t * p_ota_init_value
);

int xota_write_decode( uint8_t * p_data, uint16_t len, ota_pb_write_command_t * p_write);

#endif 
